'''
This module contains the classes:
    - Character, Player, CharacterPart

Created on 14 dec 2011

@author: Adam
'''

import clr

clr.AddReference('System.Xml.Linq')
clr.AddReference('Microsoft.Xna.Framework')

from Microsoft.Xna.Framework import Vector2, Rectangle, Color
from Microsoft.Xna.Framework.Graphics import SpriteEffects 
from Microsoft.Xna.Framework.Input import Keys
from System.Xml.Linq import XElement

###########
#Characters
###########
class Character(object):
    '''
    This is the root character class which will serve as an abstract base for
    every class from npc to the player.
    
    The character classes will mostly be loaded from a XML file of the
    .chr type.
    Ofcourse there is an option to edit every attribute individualy or in a 
    sub class but its mostly reccomended to 
    use the file loading.
    '''

    def __init__(self, xmlele = None, xmldoc = None):
        '''
        Constructor
        '''
        
        #We first try to pass the xmlele if it's None we move on and try to
        #parse the xmldoc from a path string.
        #If this too fails we just return None and let the function handel
        #the rest.
        self._parts = {}
        self.width = 0
        self.height = 0
        self.speed = 0.0
        self.position = Vector2.Zero
        self.velocity = Vector2.Zero
        self.setvarsfromxml(xmlele if xmlele else 
                            XElement.Load(xmldoc) if xmldoc else None)
        
    def setvarsfromxml(self, ele):
        """
        The XML element parse function that should be override 
        for type specific XML parsing.
        
        Recommended to start with the line:
        'Character.setvarsfromxml(self, ele)'
        where character is the base Character class.
        """
        if not ele:
            return
        
    def update(self, gametime):
        """
        Updates the characters logic.
        """
        self.position += self.velocity * gametime.ElapsedGameTime.Milliseconds
        
    def draw(self, spritebatch):
        """
        Draws the character.
        """
        for p in self._parts.values():
            p.draw(spritebatch)
        
    def getbounds(self):
        """
        Calculate the current bounds of the character.
        """
        return Rectangle(self.position.X, 
                         self.position.Y, self.width, self.height)
                         
     
    def __getitem__(self, name):
        return self._parts[name]
    
    def __setitem__(self, name, val):
        self._parts[name] = val
        val.character = self
        
    def __delitem__(self, name):
        self._parts[name].character = None
        del self._parts[name]


#Player class.
class Player(Character):
    '''
    This is the sunray player class that handels the users character,
    progress and input etc.
    '''

    def __init__(self, game):
        '''
        Constructor
        '''
        Character.__init__(self)
        self._game = game
        
    def update(self, gametime):
        Character.update(self, gametime)
        self.processinput()
        
    def processinput(self):
        #Forward
        self.velocity = Vector2.Lerp(Vector2.Zero, self.velocity, self.speed)
        
        if self._game.Input.IsKeyPressed(Keys.W):
            self.velocity -= Vector2(0, self.speed)
            
        #Backward
        if self._game.Input.IsKeyPressed(Keys.S):
            self.velocity += Vector2(0, self.speed)

        #Left
        if self._game.Input.IsKeyPressed(Keys.A):
            self.velocity -= Vector2(self.speed, 0)
            
        #Right
        if self._game.Input.IsKeyPressed(Keys.D):
            self.velocity += Vector2(self.speed, 0)
            
            
###############
#Character part
###############
class CharacterPart(object):
    """A part of a character that contains."""
    
    def __init__(self, xmlele = None):
        """Constructor"""
        self.name = "untitled"
        self.character = None
        self.texture = None
        self.color = Color.White
        self.position = Vector2.Zero
        self.rotation = 0.0
        self.origin = Vector2.Zero
        self.width = 0
        self.height = 0

        if xmlele:
            self.setvarsfromxml()
    
    def setvarsfromxml(self, ele):
        """
        The XML element parse function that should be override 
        for type specific XML parsing
        
        Recommended to start with the line:
        'CharacterPart.setvarsfromxml(self, ele)'
        where character is the base Character class.
        """
        if not ele:
            return False

    
    def getbounds(self):
        if not self.character:
            return Rectangle(int(self.position.X), int(self.position.Y), 
                self.width, self.height)
        else:
            return Rectangle(int(self.position.X) + 
                int(self.character.position.X),
                int(self.position.Y) + int(self.character.position.Y),
                self.width, self.height)


    def draw(self, spritebatch):
        spritebatch.Draw(self.texture, self.getbounds(), None, self.color,
             self.rotation, self.origin, SpriteEffects.None, 0)
        